#ifndef MOCHA_DETAIL_PLUGIN_PROXY_HPP_INCLUDED
#define MOCHA_DETAIL_PLUGIN_PROXY_HPP_INCLUDED

/**
 * @file
 */

#include <string>
#include "mocha/interface_language.hpp"
#include "mocha/object_importer.hpp"
#include "mocha/plugin_factory.hpp"
#include "mocha/pointers.hpp"

namespace mocha {
/**
 * Base for plugin proxy objects that wrap a plugin implementation.
 * @param I
 */
template<typename I>
class plugin_proxy {
public:
	typedef I interface_type;
	/// Shortcut to the plugin interface language.
	enum { interface_language = mocha::interface_language<interface_type>::language };
	/**
	 * @param factory Factory used to create the plugin instance used as an implementation.
	 * @param name Plugin type name of the implementation plugin.
	 * @param importer Importer to use for adaption (if needed).
	 */
	plugin_proxy(plugin_factory_ptr_t factory, const std::string& name, const object_importer& importer): factory_(factory), plugin_(NULL) {
		if (!factory_) {}
		if (!(plugin_ = static_cast<interface_type*>(factory_->create_object(name, importer)))) {} // Instantiation occurs here to ensure that the factory and plugin are associated.
	}
	virtual ~plugin_proxy() {
		delete plugin_;
	}
protected:
	plugin_factory_ptr_t factory() {
		return factory_;
	}
	const_plugin_factory_ptr_t factory() const {
		return factory_;
	}
	interface_type* plugin() {
		return plugin_;
	}
	const interface_type* plugin() const {
		return plugin_;
	}
private:
	plugin_factory_ptr_t factory_;
	interface_type* plugin_;
};
}

#endif

